# -*- coding: UTF-8 -*-
# 高阶函数除了可以接受函数作为参数外，还可以把函数作为结果值返回
def testReturn():
    # 闭包：当我们调用lazy_sum()时，每次调用都会返回一个新的函数，即使传入相同的参数
    f = lazy_sum(1,3,5,7,9)
    print(f())

# 立即求和
def calc_sum(*args):
    ax =0
    for n in args:
        ax = ax + n
    return ax
# 如果不需要立刻求和
def lazy_sum(*args):
    def sum():
        ax = 0
        for n in args:
            ax = ax + n
        return ax
    return sum

# 匿名函数：关键字lambda表示匿名函数，用匿名函数有个好处，因为函数没有名字，不必担心函数名冲突。
# 此外，匿名函数也是一个函数对象，也可以把匿名函数赋值给一个变量，再利用变量来调用该函数
# 匿名函数有个限制，就是只能有一个表达式，不用写return，返回值就是该表达式的结果
def testLambda():
    print("\n------testLambda----\n")
    for x in map(lambda x:x*x,range(1,10)):
        print(x)
    for x in filter(lambda x:x%2,range(1,20)):
        print(x)

import functools
# 装饰器：在函数调用前后自动打印日志，但又不希望修改now()函数的定义，这种在代码运行期间动态增加功能的方式，称之为“装饰器”（Decorator）
def testDecorator():
    now()

def log(text):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kw):
            print('%s %s():' % (text, func.__name__))
            return func(*args, **kw)
        return wrapper
    return decorator

@log('execute')
def now():
    print('2015-3-25')

# 偏函数：functools.partial，把一个函数的某些参数给固定住（也就是设置默认值），返回一个新的函数，调用这个新函数会更简单。
# 当函数的参数个数太多，需要简化时，使用functools.partial可以创建一个新的函数，
# 这个新函数可以固定住原函数的部分参数，从而在调用时更简单。
import functools
def testPartial():
    int2 = functools.partial(int,base=2)
    print(int2('1000000'))
    
    

if __name__ == '__main__':
    testReturn()
    testLambda()
    testDecorator()
    testPartial()